import asyncio
import logging
import os
import time
from typing import Dict, List
from playwright.async_api import async_playwright, Browser, Page

logger = logging.getLogger(__name__)

# 小红书相关的选择器（需要根据实际页面调整）
SELECTORS = {
    'login_button': '[data-testid="login-button"]',
    'create_button': '[data-testid="create-button"]',
    'title_input': '[data-testid="title-input"]',
    'content_textarea': '[data-testid="content-textarea"]',
    'image_upload': '[data-testid="image-upload"]',
    'tag_input': '[data-testid="tag-input"]',
    'publish_button': '[data-testid="publish-button"]',
    'confirm_button': '[data-testid="confirm-button"]',
    
    # 备用选择器（如果上面的不可用）
    'title_input_alt': 'input[placeholder*="标题"]',
    'content_textarea_alt': 'textarea[placeholder*="内容"]',
    'image_upload_alt': 'input[type="file"]',
    'publish_button_alt': 'button:has-text("发布")',
}

# 小红书URL
XIAOHONGSHU_URLS = {
    'home': 'https://www.xiaohongshu.com',
    'creator': 'https://creator.xiaohongshu.com',
    'publish': 'https://creator.xiaohongshu.com/publish/publish'
}


class XiaohongshuPublisher:
    """小红书发布器"""
    
    def __init__(self, config: Dict):
        self.config = config
        self.browser: Browser = None
        self.page: Page = None
        self.headless = config.get('headless', True)
        self.timeout = config.get('timeout', 30000)
    
    async def __aenter__(self):
        """异步上下文管理器入口"""
        await self.init_browser()
        return self
    
    async def __aexit__(self, exc_type, exc_val, exc_tb):
        """异步上下文管理器出口"""
        await self.close_browser()
    
    async def init_browser(self):
        """初始化浏览器"""
        try:
            playwright = await async_playwright().start()
            
            # 启动浏览器
            self.browser = await playwright.chromium.launch(
                headless=self.headless,
                args=[
                    '--no-sandbox',
                    '--disable-setuid-sandbox',
                    '--disable-dev-shm-usage',
                    '--disable-web-security',
                    '--disable-features=VizDisplayCompositor'
                ]
            )
            
            # 创建浏览器上下文
            context = await self.browser.new_context(
                viewport={'width': 1920, 'height': 1080},
                user_agent='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
            )
            
            # 创建页面
            self.page = await context.new_page()
            
            # 设置默认超时
            self.page.set_default_timeout(self.timeout)
            
            logger.info("Browser initialized successfully")
            
        except Exception as e:
            logger.error(f"Failed to initialize browser: {e}")
            raise
    
    async def close_browser(self):
        """关闭浏览器"""
        try:
            if self.browser:
                await self.browser.close()
                logger.info("Browser closed successfully")
        except Exception as e:
            logger.error(f"Error closing browser: {e}")
    
    async def take_screenshot(self, name: str = "screenshot"):
        """截图用于调试"""
        try:
            if self.page:
                screenshot_path = f"/tmp/{name}_{int(time.time())}.png"
                await self.page.screenshot(path=screenshot_path, full_page=True)
                logger.info(f"Screenshot saved: {screenshot_path}")
                return screenshot_path
        except Exception as e:
            logger.error(f"Failed to take screenshot: {e}")
        return None
    
    async def wait_for_element(self, selector: str, timeout: int = None) -> bool:
        """等待元素出现"""
        try:
            await self.page.wait_for_selector(selector, timeout=timeout or self.timeout)
            return True
        except Exception as e:
            logger.warning(f"Element not found: {selector}, error: {e}")
            return False
    
    async def safe_click(self, selector: str, timeout: int = None) -> bool:
        """安全点击元素"""
        try:
            if await self.wait_for_element(selector, timeout):
                await self.page.click(selector)
                await asyncio.sleep(1)  # 等待页面响应
                return True
        except Exception as e:
            logger.error(f"Failed to click {selector}: {e}")
        return False
    
    async def safe_fill(self, selector: str, text: str, timeout: int = None) -> bool:
        """安全填写文本"""
        try:
            if await self.wait_for_element(selector, timeout):
                await self.page.fill(selector, text)
                await asyncio.sleep(0.5)
                return True
        except Exception as e:
            logger.error(f"Failed to fill {selector}: {e}")
        return False
    
    async def upload_images(self, image_paths: List[str]) -> bool:
        """上传图片"""
        try:
            # 查找文件上传输入框
            upload_selectors = [
                SELECTORS['image_upload'],
                SELECTORS['image_upload_alt'],
                'input[type="file"]',
                '[accept*="image"]'
            ]
            
            upload_input = None
            for selector in upload_selectors:
                try:
                    upload_input = await self.page.wait_for_selector(selector, timeout=5000)
                    if upload_input:
                        break
                except:
                    continue
            
            if not upload_input:
                logger.error("Could not find image upload input")
                return False
            
            # 过滤存在的图片文件
            valid_images = [path for path in image_paths if os.path.exists(path)]
            
            if not valid_images:
                logger.warning("No valid image files found")
                return True  # 没有图片也算成功
            
            # 上传图片
            await upload_input.set_input_files(valid_images)
            
            # 等待图片上传完成
            await asyncio.sleep(3)
            
            logger.info(f"Uploaded {len(valid_images)} images successfully")
            return True
            
        except Exception as e:
            logger.error(f"Failed to upload images: {e}")
            return False
    
    async def navigate_to_publish_page(self) -> bool:
        """导航到发布页面"""
        try:
            # 访问创作者中心
            await self.page.goto(XIAOHONGSHU_URLS['creator'], wait_until='networkidle')
            await asyncio.sleep(2)
            
            # 检查是否需要登录
            if await self.page.locator('text=登录').count() > 0:
                logger.error("Not logged in. Please login first.")
                await self.take_screenshot("login_required")
                return False
            
            # 尝试直接访问发布页面
            await self.page.goto(XIAOHONGSHU_URLS['publish'], wait_until='networkidle')
            await asyncio.sleep(3)
            
            # 检查是否成功到达发布页面
            if await self.page.locator('text=发布笔记').count() > 0 or \
               await self.page.locator('text=标题').count() > 0:
                logger.info("Successfully navigated to publish page")
                return True
            
            logger.error("Failed to navigate to publish page")
            await self.take_screenshot("navigation_failed")
            return False
            
        except Exception as e:
            logger.error(f"Error navigating to publish page: {e}")
            await self.take_screenshot("navigation_error")
            return False
    
    async def fill_post_content(self, title: str, content: str, tags: str = "") -> bool:
        """填写帖子内容"""
        try:
            # 填写标题
            title_selectors = [
                SELECTORS['title_input'],
                SELECTORS['title_input_alt'],
                'input[placeholder*="标题"]',
                'input[placeholder*="请输入标题"]'
            ]
            
            title_filled = False
            for selector in title_selectors:
                if await self.safe_fill(selector, title):
                    title_filled = True
                    break
            
            if not title_filled:
                logger.error("Failed to fill title")
                return False
            
            logger.info(f"Title filled: {title[:50]}...")
            
            # 填写内容
            content_selectors = [
                SELECTORS['content_textarea'],
                SELECTORS['content_textarea_alt'],
                'textarea[placeholder*="内容"]',
                'textarea[placeholder*="请输入内容"]',
                '[contenteditable="true"]'
            ]
            
            content_filled = False
            for selector in content_selectors:
                if await self.safe_fill(selector, content):
                    content_filled = True
                    break
            
            if not content_filled:
                logger.error("Failed to fill content")
                return False
            
            logger.info(f"Content filled: {len(content)} characters")
            
            # 填写标签（如果有）
            if tags:
                tag_selectors = [
                    SELECTORS['tag_input'],
                    'input[placeholder*="标签"]',
                    'input[placeholder*="话题"]'
                ]
                
                for selector in tag_selectors:
                    if await self.safe_fill(selector, tags):
                        logger.info(f"Tags filled: {tags}")
                        break
            
            return True
            
        except Exception as e:
            logger.error(f"Error filling post content: {e}")
            return False
    
    async def publish_post(self) -> bool:
        """发布帖子"""
        try:
            # 查找发布按钮
            publish_selectors = [
                SELECTORS['publish_button'],
                SELECTORS['publish_button_alt'],
                'button:has-text("发布")',
                'button:has-text("立即发布")',
                '[data-testid*="publish"]'
            ]
            
            publish_clicked = False
            for selector in publish_selectors:
                if await self.safe_click(selector):
                    publish_clicked = True
                    break
            
            if not publish_clicked:
                logger.error("Failed to click publish button")
                await self.take_screenshot("publish_button_not_found")
                return False
            
            logger.info("Publish button clicked")
            
            # 等待可能的确认对话框
            await asyncio.sleep(2)
            
            # 查找确认按钮
            confirm_selectors = [
                SELECTORS['confirm_button'],
                'button:has-text("确认")',
                'button:has-text("确定")',
                'button:has-text("发布")'
            ]
            
            for selector in confirm_selectors:
                if await self.safe_click(selector, timeout=3000):
                    logger.info("Confirm button clicked")
                    break
            
            # 等待发布完成
            await asyncio.sleep(5)
            
            # 检查发布结果
            success_indicators = [
                'text=发布成功',
                'text=笔记发布成功',
                'text=已发布'
            ]
            
            for indicator in success_indicators:
                if await self.page.locator(indicator).count() > 0:
                    logger.info("Post published successfully")
                    return True
            
            # 如果没有明确的成功指示，检查URL变化
            current_url = self.page.url
            if 'publish' not in current_url or 'success' in current_url:
                logger.info("Post likely published (URL changed)")
                return True
            
            logger.warning("Publish result unclear, taking screenshot")
            await self.take_screenshot("publish_result")
            return True  # 假设成功
            
        except Exception as e:
            logger.error(f"Error publishing post: {e}")
            await self.take_screenshot("publish_error")
            return False


async def run(post_data: Dict) -> Dict:
    """执行发布脚本的主函数"""
    try:
        logger.info(f"Starting publish process for post: {post_data.get('title', 'Unknown')}")
        
        # 验证必需的数据
        if not post_data.get('title') or not post_data.get('content'):
            return {
                "success": False,
                "message": "Missing required fields: title or content"
            }
        
        config = post_data.get('config', {})
        
        # 使用异步上下文管理器
        async with XiaohongshuPublisher(config) as publisher:
            
            # 1. 导航到发布页面
            if not await publisher.navigate_to_publish_page():
                return {
                    "success": False,
                    "message": "Failed to navigate to publish page"
                }
            
            # 2. 上传图片（如果有）
            images = post_data.get('images', [])
            if images:
                if not await publisher.upload_images(images):
                    return {
                        "success": False,
                        "message": "Failed to upload images"
                    }
            
            # 3. 填写内容
            if not await publisher.fill_post_content(
                title=post_data['title'],
                content=post_data['content'],
                tags=post_data.get('tags', '')
            ):
                return {
                    "success": False,
                    "message": "Failed to fill post content"
                }
            
            # 4. 发布
            if not await publisher.publish_post():
                return {
                    "success": False,
                    "message": "Failed to publish post"
                }
            
            # 5. 获取发布后的URL（如果可能）
            final_url = publisher.page.url
            
            logger.info("Post published successfully")
            return {
                "success": True,
                "message": "Post published successfully",
                "post_url": final_url
            }
    
    except Exception as e:
        logger.error(f"Error in publish script: {e}")
        return {
            "success": False,
            "message": f"Script execution error: {str(e)}"
        }


if __name__ == "__main__":
    # 测试脚本
    test_data = {
        "title": "测试标题",
        "content": "这是一个测试内容\n\n包含多行文本\n\n#测试 #小红书",
        "images": [],
        "tags": "测试,小红书",
        "config": {
            "headless": False,  # 测试时使用可视模式
            "timeout": 30000
        }
    }
    
    async def test():
        result = await run(test_data)
        print(f"Test result: {result}")
    
    asyncio.run(test())